#基础特征计算类
import time

import pandas as pd

from Utils.DataLoaderAndSaver import DataLoaderAndSaver
from Utils.calFeatures import calLargerThanMas, closeUpPenetrateMas, calSTDS, calLessThanDays, calQuantile, calIncrease, \
    getMaOrder, maIncreaseDays, closeIncreaseDays, masUpPenetrate, volRatio, volIncreaseDays, decreaseFromMaxRecent, \
    increaseFromMinRecent, calMas, calAmplitude, calMinMaxRatio, isRecentDaysMin, isRecentDaysMax, recentDaysMax, \
    recentDaysMin, getCloseDF, calAroundMA, calSunDays, calSunDaysRatio, calRecentSunDays, calRecentNegativeDays, \
    closeDecreaseDays, calRecentSunDaysIncrease, calRecentNegativeDaysDecrease, closeUpPenetrateMa250, calHANegDays, \
    calHASunDays, HAInvert, closeInvert


class IndexFeatureCalculation:
    def __init__(self,daysBefore1=0,daysBefore2=1,yearsBefore=4):
        # 基本的配置信信息,以及加载数据
        # self.increaseTable = 'table_basic_features'
        self.dataLoaderAndSaver = DataLoaderAndSaver(
            daysBefore1=daysBefore1,
            daysBefore2=daysBefore2,
            yearsBefore=yearsBefore,
            reload=False)
        self.codes = set(list(self.dataLoaderAndSaver.allindexs.index))
        self.dailyprices = self.dataLoaderAndSaver.loadIndexDailyPrices()
        self.dailyprices.index=self.dailyprices['date']

    def calFeatures(self):
        maDays = [5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 122, 150, 180, 200, 244, 250]
        quantileDays = [30, 40, 50, 60, 90, 100, 122, 244, 366, 488, 610, 732]
        increaseDays = [3, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 122, 150, 180, 200, 244, 250, 300, 366]
        recentDays = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 122, 150, 180, 200, 244, 250, 300, 366]
        count = 0
        errorcode = []
        start = time.time()
        for code in self.codes:
            try:
                print(code)
                dailyprices = self.dailyprices[self.dailyprices['code'] == code]
                if len(dailyprices) == 0:
                    continue
                closeDF = getCloseDF(dailyprices, code)
                largerThanMasDF = calLargerThanMas(dailyprices, code, maDays, 'larger_')
                closeUpPenetrateMasDF = closeUpPenetrateMas(dailyprices, code, maDays, 'uppenetrate_')
                masDF = calMas(dailyprices, code, maDays, 'ma_')
                closestdDF = calSTDS(dailyprices, code, maDays, 'close', 'closestd_')
                volstdDF = calSTDS(dailyprices, code, maDays, 'volume', 'volstd_')
                moneystdDF = calSTDS(dailyprices, code, maDays, 'money', 'moneystd_')
                lessThanDF = calLessThanDays(dailyprices, code, [120, 250], 'lessthan_')
                quantileDF = calQuantile(dailyprices, code, quantileDays, 'quant_')
                increaseDF = calIncrease(dailyprices, code, increaseDays, 'increase_')
                # ismaOrderDF=getMaOrder(dailyprices,code,[5,10,20,30],'isma_v1')
                increaseMaDF = maIncreaseDays(dailyprices, code, maDays, 'ma_increa_')
                closeIncreaseDF = closeIncreaseDays(dailyprices, code, 'close_increa_')
                closeDecreaseDF = closeDecreaseDays(dailyprices, code, 'close_decrea_')
                masUpPenetrateDF1 = masUpPenetrate(dailyprices, code, 5, 30, 'ma_')
                masUpPenetrateDF2 = masUpPenetrate(dailyprices, code, 5, 60, 'ma_')
                masUpPenetrateDF3 = masUpPenetrate(dailyprices, code, 5, 90, 'ma_')
                masUpPenetrateDF4 = masUpPenetrate(dailyprices, code, 5, 120, 'ma_')
                masUpPenetrateDF5 = masUpPenetrate(dailyprices, code, 30, 60, 'ma_')
                masUpPenetrateDF6 = masUpPenetrate(dailyprices, code, 30, 90, 'ma_')
                masUpPenetrateDF7 = masUpPenetrate(dailyprices, code, 30, 120, 'ma_')
                masUpPenetrateDF8 = masUpPenetrate(dailyprices, code, 90, 120, 'ma_')
                masUpPenetrateDF9 = masUpPenetrate(dailyprices, code, 90, 250, 'ma_')
                masUpPenetrateDF10 = masUpPenetrate(dailyprices, code, 120, 250, 'ma_')
                volratioDF = volRatio(dailyprices, code, 'volratio')
                volIncreaseDF = volIncreaseDays(dailyprices, code, 'volincreasedays')
                decreaseFromMaxRecentDF = decreaseFromMaxRecent(dailyprices, code, recentDays, 'decrease_from_max_')
                increaseFromMinRecentDF = increaseFromMinRecent(dailyprices, code, recentDays, 'increase_from_min_')
                ampDF = calAmplitude(dailyprices, code, maDays, 'amplitude_')
                minmaxRatioDF = calMinMaxRatio(dailyprices, code, maDays, 'minmax_ratio_')
                isRecentDaysMinDF = isRecentDaysMin(dailyprices, code, maDays, 'recent_min_')
                isRecentDaysMaxDF = isRecentDaysMax(dailyprices, code, maDays, 'recent_max_')
                recentDaysMinDF = recentDaysMin(dailyprices, code, maDays, 'recent_minclose_')
                recentDaysMaxDF = recentDaysMax(dailyprices, code, maDays, 'recent_maxclose_')
                aroundMADF = calAroundMA(dailyprices, code, 488, 'around_250')
                sundaysDF = calSunDays(dailyprices, code, recentDays, 'sundays_')
                sundaysRatioDF = calSunDaysRatio(dailyprices, code, recentDays, 'sundays_ratio_')
                recentSunDaysDF = calRecentSunDays(dailyprices, code, 'recent_sundays')
                recentSunDaysIncDF = calRecentSunDaysIncrease(dailyprices, code, 'recent_sundays_')
                negDaysDF = calRecentNegativeDays(dailyprices, code, 'recent_neg_days')
                negDaysDecDF = calRecentNegativeDaysDecrease(dailyprices, code, 'recent_neg_days_')
                closeUpPenetrateMa250DF = closeUpPenetrateMa250(dailyprices, code, 'uppenetrate_250_increase')
                haNegDaysDF = calHANegDays(dailyprices, code, 'ha_negdays')
                haSunDaysDF = calHASunDays(dailyprices, code, 'ha_sundays')
                haInvertDF = HAInvert(dailyprices, code, 'ha_invert_days')
                closeInvertDF = closeInvert(dailyprices, code, 'close_invert')
                # print(lessThanDF)
                # print(quantileDF)
                finalDF = pd.concat([
                    closeDF,
                    largerThanMasDF, closeUpPenetrateMasDF, masDF,
                    closestdDF,
                    volstdDF, moneystdDF,
                    lessThanDF, quantileDF, increaseDF, increaseMaDF,
                    closeIncreaseDF, closeDecreaseDF,
                    masUpPenetrateDF1, masUpPenetrateDF2, masUpPenetrateDF3, masUpPenetrateDF4, masUpPenetrateDF5,
                    masUpPenetrateDF6, masUpPenetrateDF7,
                    masUpPenetrateDF8, masUpPenetrateDF9, masUpPenetrateDF10,
                    volratioDF, volIncreaseDF, decreaseFromMaxRecentDF, increaseFromMinRecentDF,
                    ampDF,
                    minmaxRatioDF,
                    isRecentDaysMinDF, isRecentDaysMaxDF,
                    recentDaysMinDF, recentDaysMaxDF,
                    aroundMADF,
                    sundaysDF, sundaysRatioDF, recentSunDaysDF, recentSunDaysIncDF,
                    negDaysDF,
                    negDaysDecDF,
                    closeUpPenetrateMa250DF,
                    haSunDaysDF,haNegDaysDF,
                    haInvertDF, closeInvertDF
                ], axis=1)
                code = list(finalDF.index)[0]
                finalDF.insert(0, 'code', code)
                finalDF.insert(0, 'date', self.dataLoaderAndSaver.todayDate)
                print(finalDF, finalDF.shape)
                print(','.join(finalDF.columns))
                tableName = ('indexdaily_features_' + self.dataLoaderAndSaver.todayDate + '_v4').replace('-', '_')
                self.dataLoaderAndSaver.saveData(tableName, finalDF)
            except:
                print(code, '有误')
                errorcode.append(code)
            count = count + 1
            print(count, 'of', len(self.codes))
        end = time.time()
        timeconsumption = end - start
        print('花费时间:%.2f秒,%.2f分钟,%.2f小时' % (timeconsumption, timeconsumption / 60, timeconsumption / 3600))
        print(errorcode)

etffc=IndexFeatureCalculation(-4,-3)
etffc.calFeatures()
